﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CSharp4ExpressionMetaCompiler;
using SStuff.MetaEffects.Compiler;
using SStuff.MetaEffects.Model;

namespace Sample2_CompositeShader
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        public class NoParamShaderEffect : ShaderEffect
        {
            public NoParamShaderEffect(PixelShader shader)
            {
                this.PixelShader = shader;
                PaddingBottom = 1;
                PaddingTop = 1;
                PaddingLeft = 1;
                PaddingRight = 1;
                this.UpdateShaderValue(InputProperty);
            }
            public Brush Input
            {
                get { return (Brush)GetValue(InputProperty); }
                set { SetValue(InputProperty, value); }
            }

            public static readonly DependencyProperty InputProperty =
                ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(NoParamShaderEffect), 0);
        }

        private void OnApplyShader(object sender, RoutedEventArgs e)
        {
            var expressions = new List<System.Linq.Expressions.Expression>();
            if (chkInvertX.IsChecked ?? false)
                expressions.Add(new Providers.InvertXProvider().GetShaderExpression());
            if (chkInvertY.IsChecked ?? false)
                expressions.Add(new Providers.InvertYProvider().GetShaderExpression());
            if (chkWave.IsChecked ?? false)
                expressions.Add(new Providers.WaveProvider().GetShaderExpression());

            expressions.Add(GetExtractColor());

            if (chkInvertColors.IsChecked ?? false)
                expressions.Add(new Providers.InvertColorProvider().GetShaderExpression());
            if (chkBaW.IsChecked ?? false)
                expressions.Add(new Providers.BlackAndWhiteProvider().GetShaderExpression());

            expressions.Add(GetReturnColor());

            var hlsl = ExpressionToHlsl.TranslateToHLSL(expressions.ToArray());
            var shader = HlslCompiler.Compile(hlsl, ShaderProfile.ps_2_0);
            effectTarget.Effect = new NoParamShaderEffect(shader);
        }

        private System.Linq.Expressions.Expression GetReturnColor()
        {
            System.Linq.Expressions.Expression<Action<ShaderParams>> result = o =>
                Block.Declare(new ShaderParams(), vars =>
                Block.Default
                ._(()=>vars.Color.Return()));
            return result;
        }

        private class ShaderParams
        {
            public float4 Color { get; set; }
            [Texcoord]
            public float2 TexCoord { get; set; }
            [Register(0)]
            public sampler2D InputSampler { get; set; }
        }
        private System.Linq.Expressions.Expression GetExtractColor()
        {
            System.Linq.Expressions.Expression<Action<ShaderParams>> result = o =>
                Block.Declare(new ShaderParams(), vars =>
                Block.Default
                .Assign(vars.Color, vars.InputSampler.tex2D(vars.TexCoord)));
            return result;
        }
    }
}
